<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Logging with twisted.python.log</title>
  </head>

  <body>
    <h1>Logging with twisted.python.log</h1>

    <h2>Basic usage</h2>

    <p>Twisted provides a simple and flexible logging system in the <code
    class="API">twisted.python.log</code> module.  It has three commonly used
    functions:</p>

    <dl>
      <dt><code class="API" base="twisted.python.log">msg</code></dt>
      <dd>Logs a new message.  For example:
        <pre class="python">
from twisted.python import log
log.msg('Hello, world.')
        </pre>
      </dd>
      
      <dt><code class="API" base="twisted.python.log">err</code></dt>
      <dd>Writes a failure to the log, including traceback information (if any).
      You can pass it a <code class="API"
      base="twisted.python.failure">Failure</code> or Exception instance, or
      nothing.  If you pass something else, it will be converted to a string
      with <code>repr</code> and logged.
      
      If you pass nothing, it will construct a Failure from the
      currently active exception, which makes it convenient to use in an <code
      class="python">except</code> clause:
        <pre class="python">
try:
    x = 1 / 0
except:
    log.err()   # will log the ZeroDivisionError
        </pre>
      </dd>

      <dt><code class="API" base="twisted.python.log">startLogging</code></dt>
      <dd>Starts logging to a given file-like object.  For example:
        <pre class="python">
log.startLogging(open('/var/log/foo.log', 'w'))
        </pre>
      or:
        <pre class="python">
log.startLogging(sys.stdout)
        </pre>

      By default, <code>startLogging</code> will also redirect anything written
      to <code>sys.stdout</code> and <code>sys.stderr</code> to the log.  You
      can disable this by passing <code class="python">setStdout=False</code> to
      <code>startLogging</code>.
      </dd>
    </dl>

    <p>Before <code>startLogging</code> is called, log messages will be
    discarded and errors will be written to stderr.</p>

    <h3>Logging and twistd</h3>

    <p>If you are using <code class="shell">twistd</code> to run your daemon, it
    will take care of calling <code>startLogging</code> for you, and will also
    rotate log files.  See <a href="application.xhtml#twistd">twistd and tac</a>
    and the <code class="shell">twistd</code> man page for details of using
    twistd.</p>

    <h3>Log files</h3>

    <p>The <code class="API">twisted.python.logfile</code> module provides
    some standard classes suitable for use with <code>startLogging</code>, such
    as <code class="API" base="twisted.python.logfile">DailyLogFile</code>,
    which will rotate the log to a new file once per day.</p>

    <h3>Using the Python logging module</h3>

    <p>If your application uses the logging module or you want to use its ease
    of configuration but don't want to lose twisted-produced messages,
    the observer
    <code class="API" base="twisted.python.log">PythonLoggingObserver</code>
    should be useful to you</p>

    <p>You just start it like any other observers:
        <pre class="python">
observer = log.PythonLoggingObserver()
observer.start()
        </pre>
    And then you'll just have to configure logging to do what you want:
    <a href="http://docs.python.org/lib/module-logging.html">
    logging documentation</a>.
    </p>

    <p>This method allows you to customize the log level received by the
    logging module using the <code>logLevel</code> keyword:
        <pre class="python">
log.msg("This is important!", logLevel=logging.CRITICAL)
log.msg("Don't mind", logLevel=logging.DEBUG)
        </pre>
    Unless logLevel is provided, logging.INFO is used for <code>log.msg</code>
    and logging.ERROR is used for <code>log.err</code>.
    </p>

    <p>One special care should be made when you use special configuration of
    the python logging module: some handlers (e.g. SMTP, HTTP) uses network
    so can block inside the reactor loop. <em>Nothing</em> in the bridge is
    done to prevent that.</p>

    <h2>Writing log observers</h2>

    <p>Log observers are the basis of the Twisted logging system.  An example of
    a log observer in Twisted is the <code class="API"
    base="twisted.python.log">FileLogObserver</code> used by
    <code>startLogging</code> that writes events to a log file.  A log observer
    is just a callable that accepts a dictionary as its only argument.  You can
    then register it to receive all log events (in addition to any other
    observers):</p>

    <pre class="python">
twisted.python.log.addObserver(yourCallable)
    </pre>

    <p>The dictionary will have at least two items:</p>

    <dl>
      <dt>message</dt>
      <dd>The message (a list, usually of strings)
      for this log event, as passed to <code>log.msg</code> or the
      message in the failure passed to <code>log.err</code>.</dd>
      
      <dt>isError</dt>
      <dd>This is a boolean that will be true if this event came from a call to
      <code>log.err</code>.  If this is set, there may be a <code>failure</code>
      item in the dictionary as will, with a Failure object in it.</dd>
    </dl>

    <p>Other items the built in logging functionality may add include:</p>

    <dl>
      <dt>printed</dt>
      <dd>This message was captured from <code>sys.stdout</code>, i.e. this
      message came from a <code>print</code> statement.  If
      <code>isError</code> is also true, it came from
      <code>sys.stderr</code>.</dd>
    </dl>

    <p>You can pass additional items to the event dictionary by passing keyword
    arguments to <code>log.msg</code> and <code>log.err</code>.  The standard
    log observers will ignore dictionary items they don't use.</p>

    <p>Important notes:</p>
    
    <ul>
      <li>Never raise an exception from a log observer.  If your log observer
      raises an exception, it will be removed.</li>

      <li>Never block in a log observer, as it may run in main Twisted thread.
      This means you can't use socket or syslog Python-logging backends.</li>

      <li>The observer needs to be thread safe if you anticipate using threads
      in your program.</li>
    </ul>

  </body>
</html>

